package aa

import (
	"fmt"
	"unsafe"
)

const (
	MOD_CONTROL  uintptr = 0x0002
	MOD_NOREPEAT uintptr = 0x4000
	WM_HOTKEY    uint32  = 0x0312
	HotkeyID     int32   = 1
	KEY_Y        uintptr = 89
	PM_REMOVE    uintptr = 1
	MSG_MIN      uintptr = 0
	MSG_MAX      uintptr = 0xFFFF
	SLEEP_MS     uintptr = 10

	// 事件相关常量
	WAIT_OBJECT_0      uint32  = 0          // 事件触发的返回值
	INFINITE           uint32  = 0xFFFFFFFF // 无限等待
	QS_ALLINPUT        uint32  = 0x04FF     // 等待所有输入消息
	CREATE_EVENT       uintptr = 0x00000000 // 创建事件的默认标志
	EVENT_MODIFY_STATE uintptr = 0x0002     // 修改事件状态的权限
)

type MSG struct {
	Hwnd    uintptr
	Message uint32
	WParam  uintptr
	LParam  uintptr
	Time    uint32
	Pt      POINT
}

type POINT struct {
	X int32
	Y int32
}

var (
	getForegroundWindow       = user32.NewProc("GetForegroundWindow")
	registerHotKey            = user32.NewProc("RegisterHotKey")
	unregisterHotKey          = user32.NewProc("UnregisterHotKey")
	peekMessageW              = user32.NewProc("PeekMessageW")
	translateMessage          = user32.NewProc("TranslateMessage")
	dispatchMessageW          = user32.NewProc("DispatchMessageW")
	msgWaitForMultipleObjects = user32.NewProc("MsgWaitForMultipleObjects") // 新增：等待消息和事件

	// kernel32.dll API（新增：事件操作）
	createEventW = kernel32.NewProc("CreateEventW")
	setEvent     = kernel32.NewProc("SetEvent")
	closeHandle  = kernel32.NewProc("CloseHandle")
)

// 全局变量：退出事件句柄（系统级，用于主线程监听退出信号）
var exitEvent uintptr

var A热键回调 func(foregroundHWND uintptr)

func A予热键(回调 func(foregroundHWND uintptr)) (err error) {
	A热键回调 = 回调
	if err = InitExitEvent(); err != nil {
		return
	}
	if err = RegisterHotkey(); err != nil {
		return
	}
	MessageLoop()
	return nil
}

func InitExitEvent() error {
	if err := kernel32.Load(); err != nil {
		return fmt.Errorf("加载 kernel32.dll 失败: %w", err)
	}

	// 创建系统级事件（手动重置，初始为未触发）
	event, _, err := createEventW.Call(
		uintptr(0), // lpEventAttributes：默认安全属性
		uintptr(1), // bManualReset：1=手动重置，0=自动重置
		uintptr(0), // bInitialState：0=初始未触发
		uintptr(0), // lpName：匿名事件
	)
	if event == 0 {
		return fmt.Errorf("创建退出事件失败: %v", err)
	}
	exitEvent = event
	fmt.Println("🔧 退出事件初始化完成")
	return nil
}

// 触发退出事件，供外部调用，通知主线程退出
func TriggerExitEvent() {
	if exitEvent != 0 {
		setEvent.Call(exitEvent) // 触发事件
		fmt.Println("🔔 已触发退出事件")
	}
}

// 关闭退出事件（释放资源）
func CloseExitEvent() {
	if exitEvent != 0 {
		closeHandle.Call(exitEvent) // 关闭事件句柄
		exitEvent = 0
		fmt.Println("🔌 已关闭退出事件")
	}
}

func RegisterHotkey() error {
	if err := user32.Load(); err != nil {
		return fmt.Errorf("加载 user32.dll 失败: %w", err)
	}

	success, _, err := registerHotKey.Call(
		uintptr(0),
		uintptr(HotkeyID),
		MOD_CONTROL|MOD_NOREPEAT,
		KEY_Y,
	)

	if success == 0 {
		return fmt.Errorf("热键注册失败，错误码: %v", err)
	}

	fmt.Printf("✅ 热键注册成功（Ctrl+Y，ID: %d）\n", HotkeyID)
	return nil
}

func UnregisterHotkey() {
	if user32.Load() == nil {
		unregisterHotKey.Call(uintptr(0), uintptr(HotkeyID))
		fmt.Printf("🔌 全局热键已注销（ID: %d）\n", HotkeyID)
	}
}

// 消息循环（支持主线程监听消息+退出事件）
func MessageLoop() {
	// 校验依赖
	if err := user32.Load(); err != nil {
		fmt.Printf("❌ 消息循环初始化失败：user32.dll 未加载: %v\n", err)
		return
	}
	if exitEvent == 0 {
		fmt.Println("❌ 退出事件未初始化，无法启动消息循环")
		return
	}

	var msg MSG
	fmt.Println("🔄 主线程消息循环已启动，等待热键/退出事件...")

	for {
		// 第一步：等待「消息」或「退出事件」（二选一，不阻塞主线程退出）
		// 函数原型：DWORD MsgWaitForMultipleObjects(DWORD nCount, LPHANDLE pHandles, BOOL bWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask);
		waitRet, _, _ := msgWaitForMultipleObjects.Call(
			uintptr(1),                          // nCount：等待的事件数量（1个退出事件）
			uintptr(unsafe.Pointer(&exitEvent)), // pHandles：事件句柄数组
			uintptr(0),                          // bWaitAll：0=任一事件触发即可
			uintptr(INFINITE),                   // dwMilliseconds：无限等待（但会被消息/事件唤醒）
			uintptr(QS_ALLINPUT),                // dwWakeMask：等待所有输入消息
		)

		// 情况1：退出事件触发（需要退出消息循环）
		if waitRet == uintptr(WAIT_OBJECT_0) {
			fmt.Println("🔄 收到退出事件，准备退出消息循环")
			break
		}

		// 情况2：有消息到达（处理消息）
		if waitRet == uintptr(WAIT_OBJECT_0+1) {
			// 非阻塞获取所有消息
			for {
				hasMsg, _, _ := peekMessageW.Call(
					uintptr(unsafe.Pointer(&msg)),
					uintptr(0),
					MSG_MIN,
					MSG_MAX,
					PM_REMOVE,
				)
				if hasMsg == 0 {
					break // 没有更多消息，退出循环
				}

				// 处理热键消息
				if msg.Message == WM_HOTKEY && msg.WParam == uintptr(HotkeyID) {
					fmt.Printf("📌 监听到热键事件（消息ID: %d，热键ID: %d）\n", msg.Message, msg.WParam)
					hwnd, _, _ := getForegroundWindow.Call()
					if hwnd != 0 {
						A热键回调(hwnd)
					}
				}

				// 分发消息（Windows 规范要求）
				translateMessage.Call(uintptr(unsafe.Pointer(&msg)))
				dispatchMessageW.Call(uintptr(unsafe.Pointer(&msg)))
			}
		}

		// 短暂休眠，降低CPU占用
		sleep.Call(SLEEP_MS)
	}

	// 消息循环退出后，清理事件
	CloseExitEvent()
	fmt.Println("🔄 主线程消息循环已退出")
}
